home *** CD-ROM | disk | FTP | other *** search
/ 9-Digit Zip Code Directory / 9-Digit Zip Code Directory (American Business Information) (ABIZIP-12).ISO / z4src.zip / DIAPPEND.C < prev    next >
C/C++ Source or Header  |  1993-07-16  |  10KB  |  311 lines

  1. //----------------------------------------------------------------------------
  2. //                            MODULE DESCRIPTION
  3. //
  4. //  Module:    diappend.c
  5. //   Title:    Data File I/O Library
  6. //  Notice:    John M. Weeder
  7. //                 Copyright (c) 1993. All rights reserved.
  8. //             This module contains proprietary information and should be 
  9. //                treated as confidential.
  10. //
  11. //----------------------------------------------------------------------------
  12. //                           MAINTENANCE HISTORY
  13. //
  14. // $Workfile$
  15. // $Revision$
  16. //   $Author$
  17. //     $Date$
  18. //      $Log$    
  19. //
  20. //----------------------------------------------------------------------------
  21. //                             MODULE NARRATIVE
  22. //
  23. //
  24. //    This module contains to append data to a data file. There are two 
  25. //    approaches:
  26. //        DioAppend() appends an entire file.
  27. //    or
  28. //        DioAppendNewEntry() and DioAppendUpdate()
  29. //
  30. //    DioAppendNewEntry() returns a file handle which can be written to.
  31. //    DioAppendUpdate() updates the directory entry when the user is finished
  32. //     writing to the file.
  33. //
  34. //    The code in this module should be written entirely in C. 
  35. //    Do not use any C++ constructs.
  36. //
  37. //    This module is portable to:
  38. //        DOS 3.X+
  39. //        MS Windows 3.X+
  40. //        OS/2 2.X+
  41. //        OS/2 2.0 PM
  42. //        SCO UNIX.
  43. //
  44. //    The following compilers are supported:
  45. //        MSC 6.0A
  46. //        MSC/C++ 7.0
  47. //        Borland C++ 3.1 for DOS
  48. //        Borland C++ 1.0 for OS/2 2.X
  49. //        SCO UNIX cc
  50. //
  51. //----------------------------------------------------------------------------
  52. #include <di.h>
  53.  
  54.  
  55. //----------------------------------------------------------------------------
  56. //    Global 
  57. //----------------------------------------------------------------------------
  58. typedef struct GA                                // Global data
  59. {
  60.     HPF hpf;                                        // Physical file handle
  61.     SIZET cDir;                                    // Offset of directory entry
  62.     DATAHDR hdr;                                // Header data for physical file
  63.     DATADIR dir;                                // Directory entry data
  64.     BOOL fUser;                                    // User physical file?
  65. } GA;
  66. static GA ga;
  67.  
  68.  
  69. //----------------------------------------------------------------------------
  70. //   Description:    Create a new data file entry and return a handle to allow
  71. //                          appending to the file.
  72. //    Parameters:    pcsz        Physical file name. 
  73. //                                    If upper 2 byte are zero, the lower 2 bytes
  74. //                                    specify the physical file handle
  75. //                        pcszName    Logical file name.
  76. //                        usType    Logical file type.
  77. //                        usBlock    Block size. 0 if file is not blocked.
  78. //                        phf        Variable to receive file handle to write to.
  79. //                        pfAppend    If not null, points to a boolean variable
  80. //                                    specifying whether to append to an existing file.
  81. //                                    If null, file is not appended!
  82. //                                    If true, append to existing file. Otherwise, 
  83. //                                    create.
  84. //                                    Returns TRUE if appending.
  85. //       Returns:    TRUE if successful.
  86. //----------------------------------------------------------------------------
  87. BOOL FN_E DioAppend(PCSZ pcsz, PCSZ pcszName, USHORT usType, USHORT usBlockSize, PHF phf, PBOOL pfAppend)
  88. {
  89.     FPOS fsize;
  90.     HPF hpfFind;
  91.     BOOL fAppend = pfAppend ? *pfAppend: FALSE;
  92.  
  93.  
  94.     Assert(usBlockSize <= MAX_BLOCK_SIZE);
  95.     memset(&ga, 0, sizeof(ga));            // Clear globals
  96.     *phf = -1;                                    // Initialize file handle
  97.     if (HIUSHORT(pcsz))
  98.         {
  99.         if (!DioOpenPhysical(pcsz, &ga.hpf, TRUE))
  100.             return FALSE;
  101.         ga.fUser = FALSE;
  102.         }
  103.     else
  104.         {
  105.         ga.hpf = LOUSHORT(pcsz);
  106.         Assert(ga.hpf >= 0 && ga.hpf < MAX_PHYSICAL_FILES);
  107.         Assert(di.physical[ga.hpf].fUsed);
  108.         ga.fUser = TRUE;
  109.         }
  110.                                                     // Delete existing file
  111.     if (DioFindLogical(pcszName, usType, &hpfFind, &ga.cDir, &ga.dir)
  112.     && hpfFind == ga.hpf)
  113.         {
  114.         if (fAppend)                            // Continue appending!!
  115.             {
  116.           fsize = FileGetSize(di.physical[ga.hpf].hf);
  117.           if (fsize < 0)
  118.               {
  119.               di.physical[ga.hpf].fl |= PF_ERROR;
  120.               return FALSE;
  121.               }
  122.             if (!DioHeaderRead(ga.hpf, &ga.hdr))
  123.                 return FALSE;
  124.           if (!FileSetPos(di.physical[ga.hpf].hf, fsize, FL_BEGIN))
  125.               {
  126.               di.physical[ga.hpf].fl |= PF_ERROR;
  127.               return FALSE;
  128.               }                                    // Must be last entry in file!
  129.             Assert(ga.cDir == ga.hdr.usDirectoryUsed - 1);
  130.           *phf = di.physical[ga.hpf].hf;
  131.             if (pfAppend)
  132.                 *pfAppend = TRUE;
  133.             return TRUE;
  134.             }
  135.         else
  136.             {
  137.            if (!DioDelete(HPF2PCSZ(ga.hpf), pcszName, usType))
  138.                return FALSE;
  139.             }
  140.         }
  141.     if (pfAppend)
  142.         *pfAppend = FALSE;
  143.     if (!DioHeaderRead(ga.hpf, &ga.hdr))
  144.         return FALSE;
  145.     if (ga.hdr.usDirectoryUsed >= ga.hdr.usDirectoryEntries)
  146.         {
  147.         Error("Physical file directory table is full.");
  148.         return FALSE;
  149.         }
  150.     fsize = FileGetSize(di.physical[ga.hpf].hf);
  151.     if (fsize < 0)
  152.         {
  153.         di.physical[ga.hpf].fl |= PF_ERROR;
  154.         return FALSE;
  155.         }
  156.     if ((fsize % DFH_SIZE) != 0)
  157.         {
  158.         di.physical[ga.hpf].fl |= PF_ERROR;
  159.         Error("Data file has invalid size.");
  160.         return FALSE;
  161.         }
  162.     ga.cDir = ga.hdr.usDirectoryUsed;
  163.     if (usType == DFT_RANDOM)
  164.         usBlockSize = 0;
  165.  
  166.     Assert(pcszName && pcszName[0] && strlen(pcszName) <= DFD_NAME);
  167.     Assert(usType < DFT_MAX);
  168.     Assert(usType == DFT_RANDOM || usBlockSize > 0);
  169.     Assert(phf);
  170.  
  171.     memset(&ga.dir, 0, sizeof(ga.dir));
  172.     memcpy(ga.dir.chName, pcszName, MIN(DFD_NAME, strlen(pcszName)));
  173.     ga.dir.usType = usType;
  174.     ga.dir.usBlockSize = usBlockSize;
  175.     ga.dir.fbase = fsize;
  176.     if (!FileSetPos(di.physical[ga.hpf].hf, fsize, FL_BEGIN))
  177.         {
  178.         di.physical[ga.hpf].fl |= PF_ERROR;
  179.         return FALSE;
  180.         }
  181.     *phf = di.physical[ga.hpf].hf;
  182.     return TRUE;
  183. }
  184.  
  185.  
  186. //----------------------------------------------------------------------------
  187. //   Description:    Update a data file after appending data.
  188. //    Parameters:    fSuccess        If true, append succeeded, else it failed!
  189. //       Returns:    TRUE if successful.
  190. //----------------------------------------------------------------------------
  191. BOOL FN_E DioAppendClose(BOOL fSuccess, BOOL fCrc)
  192. {
  193.     FPOS fsize;
  194.     BYTE bBuf[DFH_SIZE];
  195.     BOOL fResult = FALSE;
  196.                                                     // If failure, close and exit
  197.     if (!fSuccess || (di.physical[ga.hpf].fl & PF_ERROR))
  198.         goto ERROR_EXIT;
  199.                                                     // Get new file size
  200.     fsize = FileGetSize(di.physical[ga.hpf].hf);
  201.     if (fsize < 0)
  202.         goto ERROR_EXIT;
  203.  
  204.     ga.dir.flen = fsize - ga.dir.fbase;    // Calculate length of file
  205.     if (!ga.dir.flen)                            // Must be > 0
  206.         {
  207.         Error("Logical file is empty!");
  208.         goto ERROR_EXIT;
  209.         }
  210.  
  211.     if (ga.dir.usBlockSize)                    // If blocked, verify full blocks
  212.         {                                            //  were written
  213.         if ((ga.dir.flen % (FPOS)ga.dir.usBlockSize) != 0)
  214.             {
  215.             Error("Invalid file size.\nPartial block written.");
  216.             goto ERROR_EXIT;
  217.             }
  218.         }
  219.     else if ((ga.dir.flen % (FPOS)DFH_SIZE) != 0)
  220.         {                                            // Round to multiple of header size
  221.         SIZET cBuf = (SIZET)(DFH_SIZE - (SIZET)(ga.dir.flen % DFH_SIZE));
  222.  
  223.         memset(bBuf, 0, cBuf);
  224.         if (!FileWrite(di.physical[ga.hpf].hf, bBuf, cBuf, fsize))
  225.             goto ERROR_EXIT;
  226.         }
  227.                                                     
  228.     if (fCrc)                                    // Calculate CRC of data area
  229.         if (!FileCrc(di.physical[ga.hpf].hf, &ga.dir.crcData, ga.dir.flen, ga.dir.fbase))
  230.             goto ERROR_EXIT;
  231.                                                     // Update directory entry
  232.     if (!DioDirWrite(ga.hpf, ga.cDir, &ga.dir))
  233.         goto ERROR_EXIT;
  234.                                                     // Update header
  235.     if (ga.cDir >= ga.hdr.usDirectoryUsed)
  236.         ga.hdr.usDirectoryUsed++;            
  237.     if (!DioHeaderWrite(ga.hpf, &ga.hdr))
  238.         goto ERROR_EXIT;
  239.  
  240.     if (!DioFlush())                            // Flush file
  241.         goto ERROR_EXIT;
  242.  
  243.     fResult = TRUE;
  244.  
  245. ERROR_EXIT:
  246.     if (!ga.fUser)                                // If not a user file, close it
  247.         if (!DioClosePhysical(ga.hpf))
  248.             fResult = FALSE;
  249.  
  250.     return fResult;
  251. }
  252.  
  253.  
  254. //----------------------------------------------------------------------------
  255. //   Description:    Append an external binary file to a data file.
  256. //    Parameters:    pcsz            Physical file name. 
  257. //                                        File is opened, then closed when updating is
  258. //                                        complete.
  259. //                        pcszName        Logical file name.
  260. //                        usType        Logical file type.
  261. //                        usBlockSize    Block size. 0 if file is not blocked.
  262. //                        pcszFile        File name to append.
  263. //       Returns:    TRUE if successful.
  264. //----------------------------------------------------------------------------
  265. BOOL FN_E DioAppendFile(PCSZ pcsz, PCSZ pcszName, USHORT usType, USHORT usBlockSize, PCSZ pcszFile)
  266. {
  267.     FLAG16 fs = FL_OPEN|FL_READONLY|FL_DENYREADWRITE|FL_BINARY;
  268.     HF hf1, hf2 = -1;
  269.     FPOS fsize;
  270.     BOOL fResult = FALSE;
  271.     BYTE bBuf[sizeof(DATAHDR)];
  272.     SIZET cExtra = 0;
  273.                                                     // Get handle to write to
  274.     Assert(usBlockSize <= MAX_BLOCK_SIZE);
  275.     usBlockSize = usBlockSize ? usBlockSize: (8 _K);
  276.     if (!DioAppend(pcsz, pcszName, usType, usBlockSize, &hf1, NULL))
  277.         return FALSE;
  278.                                                     // Open external file
  279.     if (!FileOpen(&hf2, pcszFile, fs, NULL))
  280.         return FALSE;
  281.  
  282.     fsize = FileGetSize(hf2);                // Get size of external file
  283.     if (!FileSetPos(hf2, 0, FL_BEGIN))
  284.         goto ERROR_EXIT;
  285.  
  286.     if ((fsize % (FPOS)sizeof(DATAHDR)) != 0)
  287.         cExtra = sizeof(DATAHDR) - (SIZET)(fsize % (FPOS)sizeof(DATAHDR));
  288.  
  289.     if (!FileCopy(hf1, -1, hf2, 0, fsize))
  290.         goto ERROR_EXIT;
  291.  
  292.     if (cExtra)                                    // Round to correct multiple if needed!
  293.         {
  294.         memset(bBuf, 0, cExtra);
  295.         if (!FileWrite(hf1, bBuf, cExtra, -1))
  296.             goto ERROR_EXIT;
  297.         }
  298.     fResult = TRUE;
  299.  
  300. ERROR_EXIT:
  301.     if (hf2 >= 0)
  302.         FileClose(hf2);
  303.     if (!DioAppendClose(fResult, TRUE))
  304.         fResult = FALSE;
  305.  
  306.     return fResult;
  307. }
  308. //----------------------------------------------------------------------------
  309. //------------------------------- End of File --------------------------------
  310. //----------------------------------------------------------------------------
  311.